package com.sunwayhorizo.health.common.convertXMLFromObject;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 对象解析器
 */
public class Parse
{
    private StringBuilder space = new StringBuilder();
    private String dateFormat = "yyyy-MM-dd HH:mm:ss";
    private String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    private boolean showListFlag = true;
    private BaseTypeUtil baseTypeUtil = null;
    
    public Parse(BaseTypeUtil baseTypeUtil)
    {
        this.baseTypeUtil = baseTypeUtil;
    }

    public String getXml(Object obj) throws Exception
    {
        if (obj != null)
        {
            StringBuilder builder = new StringBuilder();
            if (this.xmlHeader != null)
                builder.append(this.xmlHeader);
            builder.append(parseObject(obj,false));
            return builder.toString();
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    private String parseObject(Object obj,boolean isSuperClazz) throws Exception
    {
        if (obj != null)
        {
            boolean flag = false;
            StringBuilder strBuilder = new StringBuilder();
            strBuilder.append("");
            try
            {
                Field[] arrayOfField1;
                Class clazz = Class.forName(obj.getClass().getName());
                String simpleName = obj.getClass().getSimpleName();
                int index = simpleName.lastIndexOf("_");
                if (index != -1)
                {
                    simpleName = simpleName.substring(index + 1, simpleName.length());
                }
                if( !isSuperClazz )
                strBuilder.append(this.space + "<" + simpleName + ">\n");

                //父类
                if (clazz.getSuperclass() != null && !"Object".equals(clazz.getSuperclass().getSimpleName()))
                {
                    Class sup = obj.getClass().getSuperclass(); 
                    strBuilder.append(parseObject(sup.newInstance(),true));
                }
                
                Field[] fields = clazz.getDeclaredFields();
                int j = (arrayOfField1 = fields).length;
                for (int i = 0; i < j; ++i)
                {
                    Field fieldObj = arrayOfField1[i];
                    Field field = clazz.getDeclaredField(fieldObj.getName());
                    field.setAccessible(true);
                    if( field.getType().getSimpleName().toUpperCase().indexOf("BYTE[]")!=-1){
                        //TODO 二进制部分是否需要base64进行填充
                        continue;
                    }
                    if (this.baseTypeUtil.checkBaseType(field.getType().toString()))
                    {
                        try
                        {
                            if (!(flag))
                            {
                                this.space.append("\t");
                                flag = !(flag);
                            }
                            strBuilder.append(this.space + "<" + field.getName() + ">");

                            if (field.getType().toString().indexOf("Date") != -1)
                            {
                                Date date = (Date) ((field.get(obj) == null) ? "" : field.get(obj));
                                SimpleDateFormat sf = new SimpleDateFormat(this.dateFormat);
                                strBuilder.append(sf.format(date) + "</" + field.getName() + ">\n");

                                break;
                            }

                            Object objtt = (field.get(obj) == null) ? "" : field.get(obj);
                            strBuilder.append(objtt + "</" + field.getName() + ">\n");
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                    else if (field.getType().toString().indexOf("List") != -1)
                    {
                        if (this.showListFlag)
                        {
                            strBuilder.append(this.space + "<" + field.getName() + ">\n");
                            this.space.append("\t");
                        }
                        List objList = (List) field.get(obj);
                        if (objList != null)
                        {
                            for (Iterator localIterator = objList.iterator(); localIterator.hasNext();)
                            {
                                Object objTemp = localIterator.next();
                                if (!(flag))
                                {
                                    this.space.append(" ");
                                    flag = true;
                                }
                                strBuilder.append(parseObject(objTemp,false));
                            }
                        }
                        else
                        {
                            ParameterizedType pt = (ParameterizedType) field.getGenericType() ; 
                            Class clz = (Class) pt.getActualTypeArguments()[0]; 
                            strBuilder.append(parseObject(clz.newInstance(),false));
                        }
                        if (this.showListFlag)
                        {
                            subSpace();
                            strBuilder.append(this.space + "</" + field.getName() + ">\n");
                        }
                    }
                    else
                    {
                        Object classObj = field.get(obj);
                        if( classObj == null ){
                            classObj = field.getType().newInstance();
                        }
                        if (classObj != null)
                        {
                            if (!(flag))
                            {
                                this.space.append(" ");
                                flag = true;
                            }
                            strBuilder.append(parseObject(classObj,false));
                        }
                    }
                }
                subSpace();
                if( !isSuperClazz )
                strBuilder.append(this.space + "</" + simpleName + ">\n");
                return strBuilder.toString();
            }
            catch (Exception e1)
            {
                throw e1;
            }
        }
        return null;
    }
    
    private void subSpace()
    {
        String spaceTemp = this.space.toString();
        if (spaceTemp.length() > 0)
        {
            spaceTemp = spaceTemp.substring(0, spaceTemp.length() - 1);
            this.space = new StringBuilder();
            this.space.append(spaceTemp);
        }
    }

    public String getDateFormat()
    {
        return this.dateFormat;
    }

    public void setDateFormat(String dateFormat)
    {
        this.dateFormat = dateFormat;
    }

    public String getXMLHeader()
    {
        return this.xmlHeader;
    }

    public void setXMLHeader(String header)
    {
        this.xmlHeader = header;
    }

    public boolean isShowListFlag()
    {
        return this.showListFlag;
    }

    public void setShowListFlag(boolean showListFlag)
    {
        this.showListFlag = showListFlag;
    }
}
